//	mpsf.mutesolo.c
#include "mpsf.mutesolo.h"

void *ms_class;

__declspec(dllexport) void main(void)
{
	setup((t_messlist**)&ms_class, (method)ms_new, (method)ms_free,
		(short)sizeof(t_mutesolo), (method)NULL, A_LONG, 0L);
	addmess((method)ms_setcount, "setcount", A_LONG, 0L);
	addmess((method)ms_mute, "mute", A_LONG, A_LONG, 0L);
	addmess((method)ms_solo, "solo", A_LONG, A_LONG, 0L);
	addmess((method)ms_update, "update", 0L);
	addmess((method)ms_output, "output", 0L);
	addbang((method)ms_output);
	addmess((method)ms_dump, "dump", 0L);
	addmess((method)ms_assist, "assist", A_CANT, 0L);
}

void* ms_new(long count)
{
	t_mutesolo *x;
	if(count <= 0)
	{
		error("count must be > 0");
		return NULL;
	}
	x = (t_mutesolo*)newobject(ms_class);
	x->_soloout = intout(x);
	x->_onout = outlet_new(x, NULL);
	x->_chans = NULL;
	x->_solo = 0;
	ms_setcount(x, count);
	return x;
}

void ms_free(t_mutesolo *x)
{
	if(x->_chans != NULL)
		sysmem_freeptr(x->_chans);
	freeobject((t_object*)x);
}

void ms_setcount(t_mutesolo *x, long count)
{
	long i;
	if(x->_chans != NULL)
		sysmem_freeptr(x->_chans);
	x->_chans = (t_chan*)sysmem_newptr((long)sizeof(t_chan) * count);
	for(i = 0; i < 0; i++)
	{
		x->_chans[i]._mute = 0;
		x->_chans[i]._solo = 0;
		x->_chans[i]._on = 1;
	}
	x->_count = count;
}

void ms_mute(t_mutesolo *x, long ch, long val)
{
	if(ch >= x->_count)
	{
		error("channel out of range");
		return;
	}
	x->_chans[ch]._mute = (int)CLIP(val, 0, 1);
	ms_update(x);
}

void ms_solo(t_mutesolo *x, long ch, long val)
{
	if(ch >= x->_count)
	{
		error("channel out of range");
		return;
	}
	x->_chans[ch]._solo = (int)CLIP(val, 0, 1);
	ms_update(x);
}

void ms_update(t_mutesolo *x)
{
	long i;
	x->_solo = 0;
	for(i = 0; i < x->_count; i++)
	{
		if(x->_chans[i]._solo)
		{
			x->_solo = 1;
			break;
		}
	}
	if(x->_solo)
	{
		for(i = 0; i < x->_count; i++)
			x->_chans[i]._on = x->_chans[i]._solo;
	}
	else
	{
		for(i = 0; i < x->_count; i++)
			x->_chans[i]._on = (x->_chans[i]._mute == 0) ? 1 : 0;
	}
	ms_output(x);
}

void ms_output(t_mutesolo *x)
{
	long i;
	t_atom *args;
	args = (t_atom*)sysmem_newptr((long)sizeof(t_atom) * x->_count);
	for(i = 0; i < x->_count; i++)
		SETLONG(&args[i], x->_chans[i]._on);
	outlet_list(x->_onout, 0L, (short)x->_count, args);
	outlet_int(x->_soloout, x->_solo);
	sysmem_freeptr(args);
}

void ms_dump(t_mutesolo *x)
{
	long i;
	post("begin mutesolo dump...");
	post("  solo: %d", x->_solo);
	post("  count: %d", x->_count);
	for(i = 0; i < x->_count; i++)
	{
		post("  mute: %d  solo: %d  on: %d", x->_chans[i]._mute, x->_chans[i]._solo, x->_chans[i]._on);
	}
	post("... end mutesolo dump");
}

void ms_assist(t_mutesolo *x, void *box, long msg, long arg, char *dst)
{
	if(msg == ASSIST_INLET)
	{
		strcpy(dst, "mute <N> [0|1], solo <N> [0|1], etc");
	} else {
		switch(arg)
		{
		case 0:
			strcpy(dst, "list of on/off values");
			break;
		case 1:
			strcpy(dst, "solo state");
			break;
		default:
			strcpy(dst, "????");
		}
	}
}


